package com.auto.base.widget

import android.util.Log
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import kotlin.math.roundToInt

@Composable
fun SmartRefreshLayout(
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    refreshTrigger: Dp = 20.dp,
    maxDrag: Dp = 150.dp,
    header: @Composable () -> Unit,
    content: @Composable () -> Unit
) {
    val TAG = "SmartRefreshLayout"
    val density = LocalDensity.current
    val refreshTriggerPx = with(density) { refreshTrigger.toPx() }
    Log.d(TAG, "offsetY refreshTriggerPx=$refreshTriggerPx")
    val maxDragPx = with(density) { maxDrag.toPx() }

    val dragOffset = remember { Animatable(0f) }
    val coroutineScope = rememberCoroutineScope()

    val isPulledEnough = dragOffset.value >= refreshTriggerPx

    LaunchedEffect(isRefreshing) {
        if (isRefreshing) {
            dragOffset.animateTo(refreshTriggerPx, tween(300))
        } else {
            dragOffset.animateTo(0f, tween(300))
        }
    }

    val nestedScroll = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                if (available.y > 0) {
                    val delta = (available.y / 2f).coerceAtMost(maxDragPx - dragOffset.value)
                    coroutineScope.launch {
                        dragOffset.snapTo(dragOffset.value + delta)
                    }
                    Log.d(TAG, "delta=${dragOffset.value}")
                    return Offset(0f, delta) // 👈 必须告诉系统你消费了多少
                }
                return Offset.Zero
            }

            override fun onPostScroll(
                consumed: Offset, available: Offset, source: NestedScrollSource
            ): Offset {
                Log.d(
                    TAG,
                    "consumed.x=${consumed.x},consumed.y=${consumed.y},available.x=${available.x},available.Y=${available.y},source=${source}"
                )
                if (available.y < 0 && !isRefreshing) {
                    coroutineScope.launch {
                        dragOffset.snapTo(
                            (dragOffset.value + available.y).coerceAtLeast(0f)
                        )
                    }
                }
                val delta = (available.y / 2f)
                return Offset(0f, delta) // 👈 必须告诉系统你消费了多少
//                return Offset.Zero
            }

            override suspend fun onPreFling(available: Velocity): Velocity {
                if (!isRefreshing && isPulledEnough) {
                    onRefresh()
                }
                dragOffset.animateTo(
                    if (isRefreshing) refreshTriggerPx else 0f, tween(300)
                )
                return Velocity.Zero
            }
        }
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .nestedScroll(nestedScroll)
    ) {
        // header 漂浮在顶部，并随手势动画下拉
        if (dragOffset.value > 0f || isRefreshing) {
            Box(
                modifier = Modifier
                    .offset {
                        val offsetY = (dragOffset.value - refreshTriggerPx).roundToInt()
                        Log.d(
                            TAG,
                            "offsetY = $offsetY,,,,,,dragOffset.value=${dragOffset.value},,,,,,refreshTriggerPx=$refreshTriggerPx"
                        )
                        IntOffset(0, offsetY)
                    }
                    .fillMaxWidth()
                    .height(refreshTrigger), contentAlignment = Alignment.Center) {
                header()
            }
        }

        // 内容区域整体下移
        Column(
            modifier = Modifier.offset {
                val offsetY = dragOffset.value.roundToInt()
                Log.d(TAG, "Column offsetY = $offsetY")
                IntOffset(0, offsetY)
            }) {
            content()
        }
    }
}

@Preview(showBackground = true, showSystemUi = true)
@Composable
fun TitlePreview2() {
    var refresh by remember { mutableStateOf(false) }
    SmartRefreshLayout(isRefreshing = refresh, onRefresh = {
        refresh = true
    }, header = {
        Box(
            Modifier
                .background(Color.Red)
                .fillMaxSize()
        )
    }, content = {
        Box(
            Modifier
                .background(Color.Gray)
                .fillMaxSize()
        )
    })

}